package com.wteam.framework.common.Wx.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.wteam.framework.common.Wx.service.WxLoginUtil;
import com.wteam.framework.common.enums.ResultCode;
import com.wteam.framework.common.enums.ResultUtil;
import com.wteam.framework.common.exception.ServiceException;
import com.wteam.framework.common.utils.JwtUtils;
import com.wteam.framework.common.vo.ResultMessage;
import com.wteam.framework.modules.member.entity.entity.SdMember;
import com.wteam.framework.modules.member.mapper.mapper.SdMemberMapper;
import com.wteam.framework.modules.system.entity.dos.Setting;
import com.wteam.framework.modules.system.entity.dto.WxLoginSetting;
import com.wteam.framework.modules.system.entity.enums.SettingEnum;
import com.wteam.framework.modules.system.service.SettingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;

import static cn.hutool.core.lang.Console.log;

/**
 * @author doncic
 * @date 2023/7/13 19:00
 */
@Service
@Slf4j
public class WxLoginUtilImplService implements WxLoginUtil {

    @Autowired
    private SettingService settingService;
    @Autowired
    private WxLoginUtil wxLoginUtil;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SdMemberMapper sdMemberMapper;

    @Override
    public String getRedirectUrl() {
        //先获取微信登录相关配置
        Setting setting = settingService.get(SettingEnum.WECHAT_LOGIN.name());

        if (StrUtil.isBlank(setting.getSettingValue())) {
            throw new ServiceException(ResultCode.WECHAT_LOGIN_SETTING_ERROR);
        }

        WxLoginSetting wxLoginSetting = new Gson().fromJson(setting.getSettingValue(), WxLoginSetting.class);

        String loginUrl;
        try {
            loginUrl = "https://open.weixin.qq.com/connect/qrconnect?appid="
                    + wxLoginSetting.getAppId()
                    + "&redirect_uri="
                    + URLEncoder.encode(wxLoginSetting.getRedirectURL(), String.valueOf(StandardCharsets.UTF_8))
                    + "&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect";
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        return loginUrl;
    }

    @Override
    public ResultMessage handleCallback(String code) {
        //先获取微信登录相关配置
        Setting setting = settingService.get(SettingEnum.WECHAT_LOGIN.name());

        if (StrUtil.isBlank(setting.getSettingValue())) {
            throw new ServiceException(ResultCode.WECHAT_LOGIN_SETTING_ERROR);
        }

        WxLoginSetting wxLoginSetting = new Gson().fromJson(setting.getSettingValue(), WxLoginSetting.class);
        System.out.println(wxLoginSetting);

        String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
                + wxLoginSetting.getAppId()
                + "&secret="
                + wxLoginSetting.getAppSecret()
                + "&code=" + code
                + "&grant_type=authorization_code";

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> forEntity = restTemplate.getForEntity(accessTokenUrl, String.class);
        if (forEntity.getStatusCode() == HttpStatus.OK) {
            //获取accessToken
            String body = forEntity.getBody();
            JsonObject asJsonObject = JsonParser.parseString(body).getAsJsonObject();
            String accessToken = asJsonObject.get("access_token").getAsString();
            String openid = asJsonObject.get("openid").getAsString();
            //调用服务层的方法获取用户信息
            SdMember memberInfo = wxLoginUtil.getMemberInfo(accessToken, openid);
            //进行用户信息的存储和创捷对象
            //先判断其openid是否为空，空的话就自动注册用户信息，非空就直接登录
            if (!memberInfo.getWxOpenid().equals(new SdMember().getWxOpenid())) {
                //自动帮用户注册
                memberInfo.setCreateTime(new Date());
                memberInfo.setId(Long.valueOf(IdUtil.getSnowflake(0, 0).nextIdStr()));
                memberInfo.setIsMember(false);
                memberInfo.setPhotoCount(4L);
                sdMemberMapper.insert(memberInfo);
                return ResultUtil.data(memberInfo);
            } else {
                String jwtToken = JwtUtils.getJwtToken(memberInfo.getWxOpenid(), memberInfo.getNickName());
                return ResultUtil.data("redirect:这里写网站地址?token=" + jwtToken);
            }
        }
        return null;
    }

    @Override
    public SdMember getMemberInfo(String accessToken, String openid) {
        String memberInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="
                + accessToken
                + "&openid="
                + openid;
        RestTemplate restTemplate = new RestTemplate();
        //发送get请求
        ResponseEntity<String> forEntity = restTemplate.getForEntity(memberInfoUrl, String.class);
        if (forEntity.getStatusCode() == HttpStatus.OK) {
            String body = forEntity.getBody();
            JsonObject asJsonObject = JsonParser.parseString(body).getAsJsonObject();
            //获取当前的登录用户的基本信息
            String nickname = asJsonObject.get("nickname").getAsString();
            String headimgurl = asJsonObject.get("headimgurl").getAsString();
            String sex = asJsonObject.get("sex").getAsString();
            //创建member对象返回
            SdMember sdMember = new SdMember();
            sdMember.setNickName(nickname);
            sdMember.setFace(headimgurl);
            sdMember.setSex(sex);
            sdMember.setWxOpenid(openid);
            return sdMember;
        }
        log("未获取到当前对象的信息");
        return null;
    }
}
